﻿using LowCoding.Common;
using LowCoding.Common.Security;
using LowCoding.Domain;
using LowCoding.Domain.Entity;
using LowCoding.Dto;
using LowCoding.Dto.Sys;
using Mapster;
using SqlSugar;

namespace LowCoding.Application.Sys.Role
{
    /// <summary>
    /// 角色服务实现
    /// </summary>
    public class SysRoleService : ServiceBase<SysRole, SysRoleInput, SysRoleOutput, SysRoleSearchInput, string>, ISysRoleService//继承自定义的泛型服务接口和角色模块的独立接口
    {
        /// <summary>
        /// 新增一条数据（异步）
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        //同步和异步主要用于修饰方法。当一个方法被调用时，调用者需要等待该方法执行完毕并返回才能继续执行;当一个方法被调用时立即返回，并获取一个线程执行该方法内部的业务，调用者不用等待该方法执行完毕，我们称这个方法为异步方法。
        //Task：任务，线程池线程,使用的本地队列，使线程之间的资源竞争减少
        //wait：通过wait()对单个task进行等待，task确实是异步执行,wait很好地控制了task
        public async Task<SysRoleOutput> InsertRoleAsync(SysRoleInput input)
        {
            try
            {
                //GetPrimaryKeys:获取主键    获取主键赋值给Keyarray数组
                string[] keyarray = GetPrimaryKeys(typeof(SysRole));
                //GetEntity:获取实体   通过传过来的参数 和获取主键两个参数 获取实体 赋值给entity 变量
                var entity = GetEntity(input, keyarray);//调用方法对主键进行赋值（雪花id）
                entity.Creator = "1号测试管理员";
                entity.Lastmodifier = "2号测试管理员";
                //连接数据库，进行异步添加操作
                await _client.Insertable(entity).ExecuteCommandAsync();
                return entity.Adapt<SysRoleOutput>();//映射dto进行显示
            }
            catch (Exception)
            {
                throw;
            }
        }
        /// <summary>
        /// 根据角色ID查询角色权限信息
        /// </summary>
        /// <param name="roleid"></param>
        /// <returns></returns>
        public async Task<object> GetRoleRights(string roleid)
        {
            try
            {   //调用SqlSugar中的显示方法 对模块表进行显示
                var data = await _client.Queryable<SysModule>().ToListAsync();//查询角色类中的信息
                //使用Mapster 对Dto 进行映射转换
                List<SysModuleOutput> modulelist = data.Adapt<List<SysModuleOutput>>();
                //转换成实体目标后通过传过来的参数roleid 和数据库中的角色Id进行角色模块表条件查询 
                //把查询出来的数据 赋值给 rightlist
                List<SysRight> rightlist = await _client.Queryable<SysRight>().Where(it => it.RgtRoleId == roleid).ToListAsync();
                //查询出来的rightlist中的数据 根据 角色模块表.id == 模块表.id
                //使用FindIndex 方法 获取它的第一个元素索引,否则就返回1
                var moduledata = modulelist.Select(it => new 
                { it.Id, it.MdlCode, it.MdlName, it.MdlParent, HasRight = 
                rightlist.FindIndex(t => t.Id == it.Id) > -1 }).ToList();
                //FindIndex()方法 返回数组中获取的第一个元素的索引，否则返回-1
                //FindIndex(Predicate<T> match)，泛型委托，只能接受一个返回值，返回值是bool类型
                return new { moduledata };
            }
            catch (Exception)
            {
                throw;
            }
            
        }
        /// <summary>
        /// 查询角色
        /// </summary>
        /// <returns></returns>
        public async Task<List<SysRole>> SysRolePageTwo()
        {
            try
            {
                //使用sql语句查询未删除角色的信息
                string sql = @"select * from SYSROLE s where s.isdel=0 ";
                //实例化Sqlsugar的自定义表类型集合 
                List<SugarParameter> parmList = new List<SugarParameter>();
                var data = await _client.Ado.SqlQueryAsync<SysRole>(sql, parmList);//进行数据库连接
                return data;//返回查询到的数据
            }
            catch (Exception)
            {
                throw;
            }
            
        }

        /// <summary>
        /// 角色下拉框
        /// </summary>
        /// <returns></returns>
        public async Task<List<RoleOptions>> GetRoleOptionsAsync()
        {
            try
            {
                //获取当前登录用户
                var user = AppManager.GetCurrentUser();
                //根据条件判断查询 
                //如果获取当前的用户不为空 并且企业Id不为-1 -2 是角色管理员 未删除的角色信息
                var data = await _client.Queryable<SysRole>()
                    .Where(it => it.Isdel == "0")
                    .WhereIF(user != null && user.UsrFltId != "-1" && user.UsrFltId != "-2", it => it.RleIsp == "0")
                    .Select(it => new RoleOptions
                    {
                        Id = it.Id,
                        RleCode = it.RleCode,
                        RleName = it.RleName,
                        RleIsp = it.RleIsp
                    })
                    .ToListAsync();
                return data;
            }
            catch (Exception)
            {
                throw;
            }
        }
        /// <summary>
        /// 更新一条数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<SysRoleOutput> RoleUpdateAsync(SysRoleInput input)
        {
            try
            {
                //传入参数 获取实体 赋值给 entity 变量1
                var entity = await GetEntityAsync(input, null, false);
                //这里是因为测试 所以就直接写死 修改人员为1号测试管理员
                entity.Lastmodifier = "1号测试管理员";
                //调用SqlSugar更新语句 刚刚获取到的entity变量进行更新
                int result = await _client.Updateable(entity).ExecuteCommandAsync();
                //如果大于等于0 就是没数据的话 就更新失败
                if (result <= 0)
                    throw new Exception("更新失败");
                return entity.Adapt<SysRoleOutput>();
            }
            catch (Exception)
            {
                throw;
            }
            
        }
        /// <summary>
        /// 删除多个角色
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<UpdateResult> DelRolesAsync(List<string> id)
        {
            //一般删除修改 添加的话 都要加事务,因为 有事务的一致性 如果有一条数据不成功那么这整个都执行不成功
            //开始提交事务
            _client.Ado.BeginTran();
            try
            {
                //调用SqlSugar中的删除方法 对角色表进行 条件删除单条数据
                await _client.Deleteable<SysRole>().Where(it => id.Contains(it.Id)).ExecuteCommandAsync();
                //调用SqlSugar中的删除方法 对角色表进行 条件删除多条数据
                await _client.Deleteable<SysUserrole>().Where(it => id.Contains(it.RleId)).ExecuteCommandAsync();
                //提交事务
                _client.Ado.CommitTran();
                //修改成功
                return new UpdateResult { result = true };
            }
            catch (Exception)
            {
                //RollbackTran  事务失败,进行回滚
                _client.Ado.RollbackTran();
                throw;
            }
            
        }
    }
}
